package com.cicc.beergamevirtualsimulationsystem.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cicc.beergamevirtualsimulationsystem.common.enums.commonEnum.LevelEnum;
import com.cicc.beergamevirtualsimulationsystem.common.enums.userTypeEnum.RoleType;
import com.cicc.beergamevirtualsimulationsystem.common.errorEnum.ParameterErrorEnum;
import com.cicc.beergamevirtualsimulationsystem.common.exception.BizException;
import com.cicc.beergamevirtualsimulationsystem.common.exception.ExceptionFactory;
import com.cicc.beergamevirtualsimulationsystem.common.webSocket.config.WebSocketMessageSender;
import com.cicc.beergamevirtualsimulationsystem.entity.ParameterEntity;
import com.cicc.beergamevirtualsimulationsystem.entity.RoleTypeEntity;
import com.cicc.beergamevirtualsimulationsystem.mapper.ParameterMapper;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.dto.CurrentRoomParameterDto;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.dto.InnerGameParameterDto;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.req.InnerGameParameterUpdateReq;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.req.ParameterCreatorReq;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.dto.DefaultParameterDto;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.dto.RoomParameterDto;
import com.cicc.beergamevirtualsimulationsystem.model.parameter.req.ParameterUpdateReq;
import com.cicc.beergamevirtualsimulationsystem.model.userType.RoleTypeParameterDto;
import com.cicc.beergamevirtualsimulationsystem.service.ParameterService;
import com.cicc.beergamevirtualsimulationsystem.service.RoleTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class ParameterServiceImpl extends ServiceImpl<ParameterMapper, ParameterEntity> implements ParameterService {

    private final RoleTypeService  roleTypeService;

    /**
     * 查询默认参数
     *
     * @return
     */
    @Override
    public DefaultParameterDto queryDefaultParameter() {
        // 默认基础配置
        LambdaQueryWrapper<ParameterEntity> wrapper = new LambdaQueryWrapper<ParameterEntity>()
                .eq(ParameterEntity::getLevel, LevelEnum.SYSTEM_DEFAULT.getCode());
        ParameterEntity parameter = getOne(wrapper);
        DefaultParameterDto parameterDto = new DefaultParameterDto();
        BeanUtils.copyProperties(parameter, parameterDto);
        // 默认角色基础配置
        LambdaQueryWrapper<RoleTypeEntity> roleTypeWrapper = new LambdaQueryWrapper<RoleTypeEntity>()
                .eq(RoleTypeEntity::getLevel, LevelEnum.SYSTEM_DEFAULT.getCode())
                // 主持人角色不展示给前端
                .ne(RoleTypeEntity::getRoleType, RoleType.CUSTOMER.getCode())
                .orderByAsc(RoleTypeEntity::getOrderBy);
        List<RoleTypeParameterDto> defaultParameterDtos = roleTypeService.list(roleTypeWrapper)
                .stream().map(v -> {
                    RoleTypeParameterDto roleTypeParameterDto = new RoleTypeParameterDto();
                    BeanUtils.copyProperties(v, roleTypeParameterDto);
                    return roleTypeParameterDto;
                }).toList();
        parameterDto.setRoleTypeList(defaultParameterDtos);
        return parameterDto;
    }
    /**
     * 创建游戏参数
     *
     * @param parameterCreatorReq
     * @return 参数id
     */
    @Override
    public String createParameter(ParameterCreatorReq parameterCreatorReq) {
        ParameterEntity entity = new ParameterEntity();
        BeanUtils.copyProperties(parameterCreatorReq, entity);
        save(entity);
        return entity.getId();
    }

    /**
     * 查询当前房间的配置参数
     *
     * @param roomId
     * @return
     */
    @Override
    public RoomParameterDto queryParameterByRoomId(String roomId) {
        RoomParameterDto roomParameterDto = new RoomParameterDto();
        // 房间基础配置
        ParameterEntity parameterEntity = getOne(new LambdaQueryWrapper<ParameterEntity>().eq(ParameterEntity::getRoomId, roomId));
        if(Objects.isNull(parameterEntity)){
            throw ExceptionFactory.bizException(ParameterErrorEnum.PARAMETER_NULL_ERROR.getCode(), ParameterErrorEnum.PARAMETER_NULL_ERROR.getDesc());
        }
        CurrentRoomParameterDto currentRoomParameterDto = new CurrentRoomParameterDto();
        BeanUtils.copyProperties(parameterEntity, currentRoomParameterDto);
        // 不同角色基础配置
        List<RoleTypeParameterDto> roleTypeEntities = roleTypeService.list(new LambdaQueryWrapper<RoleTypeEntity>().eq(RoleTypeEntity::getRoomId, roomId))
                .stream().map(v->{
                    RoleTypeParameterDto roleTypeEntity = new RoleTypeParameterDto();
                    BeanUtils.copyProperties(v, roleTypeEntity);
                    return roleTypeEntity;
                }).toList();

        roomParameterDto.setCurrentRoomParameter(currentRoomParameterDto);
        roomParameterDto.setRoleTypeParameterList(roleTypeEntities);
        return roomParameterDto;
    }

    /**
     * 更新房间配置
     *
     * @param parameterUpdateReq
     * @return
     */
    @Override
    public void updateRoomParameter(ParameterUpdateReq parameterUpdateReq) {
        String roomId = parameterUpdateReq.getRoomId();
        // 更新角色配置
        List<RoleTypeEntity> roleTypeParameterList = parameterUpdateReq.getRoleTypeParameterList()
                .stream()
                .map(v -> {
                    RoleTypeEntity roleTypeEntity = new RoleTypeEntity();
                    BeanUtils.copyProperties(v, roleTypeEntity);
                    roleTypeEntity.setRoomId(roomId);
                    roleTypeEntity.setLevel(LevelEnum.USER_DEFINED.getCode());
                    return roleTypeEntity;
                }).toList();
        // 先删除在插入
        roleTypeService.remove(new LambdaQueryWrapper<RoleTypeEntity>().eq(RoleTypeEntity::getRoomId, roomId));
        roleTypeService.saveBatch(roleTypeParameterList);

        // 获取当前房间配置并根据房间id更新
        CurrentRoomParameterDto currentRoomParameter = parameterUpdateReq.getCurrentRoomParameter();
        ParameterEntity parameterEntity = new ParameterEntity();
        BeanUtils.copyProperties(currentRoomParameter, parameterEntity);
        parameterEntity.setRoomId(roomId);

        Integer totalPeopleNumber = 0;
        // 更新人数
        for (int i = 0; i < roleTypeParameterList.size(); i++) {
            RoleTypeEntity roleTypeEntity = roleTypeParameterList.get(i);
            totalPeopleNumber += roleTypeEntity.getRoleNum();
        }
        parameterEntity.setTotalPeopleNum(totalPeopleNumber);
        update(parameterEntity, new LambdaQueryWrapper<ParameterEntity>().eq(ParameterEntity::getRoomId, roomId));
    }

    /**
     * 更新房间配置【未开局】
     * @param innerGameParameterUpdateReq
     * @return
     */
    @Override
    public InnerGameParameterDto updateInnerGameParameter(InnerGameParameterUpdateReq innerGameParameterUpdateReq) {
        if(Objects.isNull(innerGameParameterUpdateReq.getRoomId())){
            throw new BizException(ParameterErrorEnum.ROOM_ID_PARAMETER_NULL_ERROR.getCode(),ParameterErrorEnum.ROOM_ID_PARAMETER_NULL_ERROR.getDesc());
        }

        LambdaUpdateWrapper<ParameterEntity> wrapper = new LambdaUpdateWrapper<ParameterEntity>()
                .set(Objects.nonNull(innerGameParameterUpdateReq.getGameTime()), ParameterEntity::getGameTime, innerGameParameterUpdateReq.getGameTime())
                .set(Objects.nonNull(innerGameParameterUpdateReq.getCycles()), ParameterEntity::getCycles, innerGameParameterUpdateReq.getCycles())
                .eq(ParameterEntity::getRoomId, innerGameParameterUpdateReq.getRoomId());
        boolean updatedFlag = update(wrapper);
        // 更新成功
        if(updatedFlag){
            InnerGameParameterDto currentRoomParameterDto = new InnerGameParameterDto();
            BeanUtils.copyProperties(innerGameParameterUpdateReq,currentRoomParameterDto);
            return currentRoomParameterDto;
        }
        throw  new BizException("更新失败，请检查重试！");
    }
}
